package cn.thoughtworks.school.services;

import cn.thoughtworks.school.entities.*;
import cn.thoughtworks.school.handlers.BusinessException;
import cn.thoughtworks.school.repositories.BasicQuizChoicesRepository;
import cn.thoughtworks.school.repositories.BasicQuizRepository;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.transaction.Transactional;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Service
public class BasicQuizExcelImportService {

  private static final String SINGLE_CHOICE = "SINGLE_CHOICE";
  private static final String MULTIPLE_CHOICE = "MULTIPLE_CHOICE";
  private static final String BASIC_BLANK_QUIZ = "BASIC_BLANK_QUIZ";

  @Autowired
  private BasicQuizRepository basicQuizRepository;
  @Autowired
  private BasicQuizChoicesRepository basicQuizChoicesRepository;
  @Autowired
  private UserCenterService userCenterService;
  private Workbook workbook;
  private Sheet firstSheet;

  public void init(MultipartFile file) throws IOException, BusinessException {
    this.workbook = this.getWorkbook(file);
    this.firstSheet = this.getFirstSheet(workbook);
  }

  private Sheet getFirstSheet(Workbook workbook) throws BusinessException {
    Sheet sheet = workbook.getSheetAt(0);
    if (Objects.isNull(sheet)) {
      throw new BusinessException("Could not find the first sheet");
    }
    return sheet;
  }

  private Workbook getWorkbook(MultipartFile file) throws IOException {
    Workbook workbook;
    String fileName = file.getOriginalFilename();
    boolean isExcel2003 = true;
    if (fileName.matches("^.+\\.(?i)(xlsx)$")) {
      isExcel2003 = false;
    }
    InputStream is = file.getInputStream();

    if (isExcel2003) {
      workbook = new HSSFWorkbook(is);
    } else {
      workbook = new XSSFWorkbook(is);
    }
    return workbook;
  }

  @Transactional
  public void importExcel(User current) throws BusinessException {
    for (int i = 1; i <= firstSheet.getLastRowNum(); ++i) {
      Row row = firstSheet.getRow(i);
      String quizType = getQuizType(row);
      BasicQuiz basicQuiz = getBasicQuiz(row, quizType, current);
      basicQuizRepository.save(basicQuiz);
      if (!quizType.equals(BASIC_BLANK_QUIZ)) {
        importOptions(basicQuiz, row);
      }
    }
  }

  private void importOptions(BasicQuiz basicQuiz, Row row) {
    List<BasicQuizChoices> basicQuizChoices = new ArrayList<>();
    for (int i = 3; i < row.getLastCellNum(); ++i) {
      Integer index = i - 3;
      BasicQuizChoicesComplexPK complexPK = new BasicQuizChoicesComplexPK(index, basicQuiz.getId());
      Cell optionCell = row.getCell(i);
      optionCell.setCellType(Cell.CELL_TYPE_STRING);
      basicQuizChoices.add(new BasicQuizChoices(complexPK, optionCell.getStringCellValue()));
    }
    basicQuizChoicesRepository.saveAll(basicQuizChoices);
  }

  private BasicQuiz getBasicQuiz(Row row, String quizType, User current) {
    Long organizationId = userCenterService.getUserCurrentOrganizationId(current.getId());
    String answer;
    String description = row.getCell(1).getStringCellValue();
    Cell answerCell = row.getCell(2);
    answerCell.setCellType(Cell.CELL_TYPE_STRING);
    answer = answerCell.getStringCellValue();
    return new BasicQuiz(description, quizType, answer, current.getId(),organizationId);
  }

  private String getQuizType(Row row) throws BusinessException {
    String type = row.getCell(0).getStringCellValue();
    if (type.equals("单选题")) {
      return SINGLE_CHOICE;
    }
    if (type.equals("多选题")) {
      return MULTIPLE_CHOICE;
    }
    if (type.equals("填空题")) {
      return BASIC_BLANK_QUIZ;
    }
    throw new BusinessException("题目类型错误");
  }

}
